﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GmepModelInterface.h"
#include "Coordinate3d.h"
#include "IDbObject.h"
#include "OwnerPtr.h"
#include "DataSchemaPrivate.h"

namespace gcmp
{
    class Coordinate3d;
    class ElementId;
    class IDbObject;
    class IElement;
    class Vector3d;
}

namespace gmep
{
    class IConnectorManager;
    class ISectionData;
    class IConnectorInfo;
    enum class MEPSystemClassification;
    enum class FlowDirectionType;

    /// \brief 连接点类型
    SERIALIZABLE_ENUM_CLASS(ConnectorType)
    {
        Invalid = -1,  ///< 无效类型
        End = 0,       ///< 设备、管接头、管线端点的连接点属于这种类型
        Curve = 1      ///< 管线中间某一点上的连接点，比如管道上连接Tap管接头或者风口的连接点
    };

    /// \brief InstanceConnector连接点类型
    ///
    /// InstanceConnector连接点类型，主要用于区分是族中自带的连接点，或者是自定义的连接点
    SERIALIZABLE_ENUM_CLASS(InstanceConnectorType)
    {
        Invalid = -1,                            ///< 无效类型
        InstanceSelfContainedConnector = 0,             ///< 族中自带的连接点
        CustomConnector = 1,                            ///< 自定义连接点
    };

    /// \brief 连接点所属专业
    SERIALIZABLE_ENUM_CLASS(ConnectorDomain)
    {
        DomainUndefined = -1,           ///< 无效类型
        DomainHvac = 0,                 ///< 风管上的连接点 HVAC (duct) connector
        DomainElectrical = 1,           ///< 电气连接点 Electrical connector 
        DomainPiping = 2,               ///< 管道连接点 Piping connector 
        DomainCableTray = 3,            ///< 电缆桥架连接点 Connector of cable trays
        DomainConduit = 4,              ///< 电线导管连接点 Connector of conduits
        DomainBusway = 5,               ///< 母线槽连接点 Connector of busway
    };

    /// \brief 连接点连接状态
    SERIALIZABLE_ENUM_CLASS(ConnectorState)
    {
        Type_None = -1,     // 未连接
        Type_ConnectNormal = 0,      // 正常的连接
        Type_ConnectLinkLinked = 1,       // 连接链接设备,并且是链接状态
        Type_ConnectLinkUnload = 2,       // 连接链接设备，并且是卸载状态
    };

    ///\brief 连接点
    class GMEP_MODEL_INTERFACE_EXPORT IConnector : public gcmp::IDbObject
    {
        DEFINE_CAST_DERIVED(IConnector, IDbObject);

    public:
        /// \brief 析构函数
        virtual ~IConnector() {}

    public:
        /// \brief 得到连接名称
        /// \return 连接名称
        virtual std::wstring GetName()const = 0;

        /// \brief 设置该行为所属Element
        /// \param pOwnerElement 所属Element
        /// \return bool
        virtual bool SetOwnerElement(gcmp::IElement* pOwnerElement) = 0;

        /// \brief 获得该外部对象所属Element
        /// \return 所属Element
        virtual const gcmp::IElement* GetOwnerElement() const = 0;

        /// \brief 获得该外部对象所属Element
        /// \return 所属Element
        virtual gcmp::IElement* GetOwnerElement() = 0;


        /// \brief 得到连接点id
        /// \return 连接点id
        virtual int GetConnectorId() const = 0;

        /// \brief 获得构建编辑器中为连接点定义的业务信息Id，比如201，203之类
        /// \return 连接点业务信息Id
        virtual int GetConnectionDataId() const = 0;

        /// \brief 设置构建编辑器中为连接点定义的业务信息Id，比如201，203之类；主要用于族服务后处理中承接连接点解析过来的数据
        virtual bool SetConnectionDataId(int connectionDataId) = 0;

        /// \brief 获取当前连接点上的系统分类
        virtual MEPSystemClassification GetSystemClassification()const = 0;

        /// \brief 设置当前连接点上的系统分类
        /// \return 返回true表示成功，否则表示失败
        virtual bool SetSystemClassification(MEPSystemClassification systemClassification) = 0;

        /// \brief 得到连接点上的系统元素Id
        /// \return 系统元素Id
        virtual gcmp::ElementId GetMepSystemId() const = 0;

        /// \brief 获取当前连接点的流向
        virtual FlowDirectionType GetFlowDirectionType()const = 0;

        /// \brief 设置当前连接点的流向
        /// \return 返回true表示成功，否则表示失败
        virtual bool SetFlowDirectionType(FlowDirectionType flowDirectionType) = 0;

        /// \brief 得到连接点类型
        /// \return 连接点类型
        /// \see ConnectorType
        virtual ConnectorType GetConnectorType() const = 0;

        /// \brief 得到连接点专业
        /// \return 连接点专业
        virtual ConnectorDomain GetConnectorDomain() const = 0;


        /// \brief 判断是不是一个构件上的连接点
        /// \return 返回true表示是一个构件连接点，否则不是
        virtual bool IsInstanceConnector() const = 0;

        /// \brief 获取设备连接点的类型
        /// \return 获取设备连接点的类型
        virtual InstanceConnectorType GetInstanceConnectorType() const = 0;

        /// \brief 判断是不是一个启用的连接
        /// \return 返回true表示连接点已经启用了，否则是一个没有启用的连接点
        virtual bool IsEnable() const = 0;


        /// \brief 禁用连接点
        /// \return 返回true表示成功禁用连接点，否则表示失败
        virtual bool Disable() = 0;

        /// \brief 启用连接点。默认连接点都是启用的。
        /// \return 返回true表示成功启用连接点，否则表示失败
        virtual bool Enable() = 0;

        /// \brief 得到被连接对象元素Id
        /// 
        /// DomainElectrical专业允许一个连接点连接多个连接点外，其它专业只允许一对一的连接关系
        /// 对DomainElectrical专业，返回得是第一个被连接对象元素Id，需要得到所有被连接对象元素Id时，
        ///可以通过GetAllConnectedConnectors接口间接得到
        /// \return 被连接对象元素Id
        virtual gcmp::ElementId GetConnectedConnectorOwnerElementId() const = 0;

        /// \brief 得到被连接对象连接点id
        /// 
        /// DomainElectrical专业允许一个连接点连接多个连接点外，其它专业只允许一对一的连接关系
        /// 对DomainElectrical专业，返回得是第一个被连接对象连接点id，需要得到所有被连接对象连接点id时，
        ///可以通过GetAllConnectedConnectors接口间接得到
        /// \return 被连接对象连接点id
        virtual int GetConnectedConnectorId() const = 0;

        /// \brief 得到被连接对象指针，分同文档连接点相连和不同文档连接点相连两种情况。
        /// 同文档连接点相连通过Connector直接相连并记录ConnectedConnectorOwnerElementId方式。
        /// 不同文档连接点相连通过MepElementJoin方式。
        /// \see GetConnectedConnectorOwnerElementId()解释
        /// 对连接点与MepElementJoin相连的情况，则是返回主文档的被连接对象指针：
        /// 1、当连接点在主文档，被连接对象的连接点在链接文档时，返回被连接点对象在主文档中的代理，即ILinkElementProxy对象的指针。
        /// 2、当连接点在链接文档，被连接对象的连接点在主文档时，返回连接对象的指针。
        /// \return 被连接对象指针
        virtual gcmp::IElement *GetConnectedElement() = 0;

        /// \brief 得到被连接对象指针，分同文档连接点相连和不同文档连接点相连两种情况。
        /// 同文档连接点相连通过Connector直接相连并记录ConnectedConnectorOwnerElementId方式。
        /// 不同文档连接点相连通过MepElementJoin方式。
        /// \see GetConnectedConnectorOwnerElementId()解释
        /// 对连接点与MepElementJoin相连的情况，则是返回主文档的被连接对象指针：
        /// 1、当连接点在主文档，被连接对象的连接点在链接文档时，返回被连接点对象在主文档中的代理，即ILinkElementProxy对象的指针。
        /// 2、当连接点在链接文档，被连接对象的连接点在主文档时，返回连接对象的指针。
        /// \return 被连接对象指针
        virtual const gcmp::IElement *GetConnectedElement() const = 0;

        /// \brief 得到连接点坐标系
        /// 
        /// 其中坐标系的Z方向为连接点方向（GetZ()）
        /// \return 连接点坐标系
        virtual gcmp::Coordinate3d GetCoordinate() const = 0;

        /// \brief 得到2D连接点坐标系
        /// 
        /// \return 2D连接点坐标系
        virtual gcmp::Coordinate3d Get2dCoordinate(const std::wstring &modelViewUserDataId) const = 0;
        virtual gcmp::Coordinate3d GetBase2dCoordinate(const std::wstring &modelViewUserDataId) const = 0;

        /// \brief 设置2D连接点坐标系
        /// 
        /// \return 返回true表示设置成功，否则表示失败
        virtual bool SetBase2dCoordinate(const std::wstring &modelViewUserDataId, const gcmp::Coordinate3d& coordinate2d) = 0;

        /// \brief 得到连接点基础坐标系。只对族对象有效。
        /// \return 连接点基础坐标系
        virtual gcmp::Coordinate3d GetBaseCoordinate() const = 0;

        /// \brief 设置基础坐标系。只对族对象有效，机电平台内部调用接口，外部禁止调用
        /// \param baseCoordinate 基础坐标系
        /// \return 返回true表示设置成功，否则表示失败
        virtual bool SetBaseCoordinate(const gcmp::Coordinate3d& baseCoordinate) = 0;

        /// \brief 得到截面信息
        /// 
        /// 对管道等类型对象，截面信息是实时计算出来的。
        /// \return 截面信息
        virtual gcmp::OwnerPtr<ISectionData> GetSectionData() const = 0;

        ///\brief 设置截面信息。 内部调用接口，外部禁止调用。
        virtual bool SetSectionData(gcmp::OwnerPtr<ISectionData> sectionData) = 0;

        /// \brief 得到连接点管理器指针
        /// \return 连接点管理器指针
        virtual const IConnectorManager* GetOwnerConnectorManager() const = 0;

        /// \brief 得到连接点管理器指针
        /// \return 连接点管理器指针
        virtual IConnectorManager* GetOwnerConnectorManager() = 0;

        /// \brief 判断是否有连接关系
        /// \return 返回true表示有连接关系，否则没有连接关系
        virtual bool IsConnected() const = 0;

        /// \brief 获取连接点连接状态
        /// \return 返回连接点连接状态
        virtual ConnectorState GetConnectorState() const = 0;

        /// \brief 判断是否与另一个连接点有连接关系
        /// \param pOtherConnector 另一个连接点
        /// \return 返回true表示有连接关系，否则没有连接关系
        virtual bool IsConnectedTo(const IConnector* pOtherConnector) const = 0;


        /// \brief 得到被连接点指针
        ///
        /// DomainElectrical专业允许一个连接点连接多个连接点，其它专业只允许一对一的连接关系
        /// 对DomainElectrical专业，返回得是第一个被连接对象信息，
        /// \return 被连接点指针
        virtual const IConnector* GetConnectedConnector() const = 0;

        /// \brief 得到被连接点指针
        ///
        ///\see GetConnectedConnectorOwnerElementId()
        /// \return 被连接点指针
        virtual IConnector* GetConnectedConnector() = 0;

        /// \brief 得到所有被连接点指针
        ///
        /// DomainElectrical专业允许一个连接点连接多个连接点，其它专业只允许一对一的连接关系
        /// \return 所有被连接点指针
        virtual std::vector<const IConnector*> GetAllConnectedConnectors() const = 0;

        /// \brief 得到所有被连接点指针
        ///
        /// DomainElectrical专业允许一个连接点连接多个连接点，其它专业只允许一对一的连接关系
        /// \return 所有被连接点指针
        virtual std::vector<IConnector*> GetAllConnectedConnectors() = 0;

        /// \brief 与另一个连接点建立连接关系
        /// \param pOtherConnector 另一个连接点
        /// \return 返回true表示建立连接关系，否则表示失败
        virtual bool ConnectTo(IConnector* pOtherConnector) = 0;

        /// \brief 与链接连接点建立连接关系
        /// \param pOtherConnector 另一个连接点
        /// \return 返回true表示建立连接关系，否则表示失败
        virtual bool ConnectToLinkConnector(const IConnector* pOtherConnector) = 0;

        /// \brief 与另一个连接点断开连接关系
        /// \param pOtherConnector 另一个连接点
        /// \param isErrorConnector 如果是错误连接，则表示此次断开连接是因为错误的行为导致的断开，会被GmepErrorConnectorDisconnectEventHandler收集到
        /// \return 返回true表示成功断开连接关系，否则表示失败
        virtual bool DisconnectFrom(IConnector* pOtherConnector) = 0;

        /// \brief 与 链接 连接点断开连接关系
        /// \param pOtherConnector 另一个 链接  连接点
        /// \param isErrorConnector 如果是错误连接，则表示此次断开连接是因为错误的行为导致的断开，会被GmepErrorConnectorDisconnectEventHandler收集到
        /// \return 返回true表示成功断开连接关系，否则表示失败
        virtual bool DisconnectFromLink(const IConnector* pOtherConnector) = 0;

        /// \brief 与另一个连接点断开连接关系(该连接断开为错误断开，后续有提示)
        /// \param pOtherConnector 另一个连接点
        /// \param isErrorConnector 如果是错误连接，则表示此次断开连接是因为错误的行为导致的断开，会被GmepErrorConnectorDisconnectEventHandler收集到
        /// \return 返回true表示成功断开连接关系，否则表示失败
        virtual bool DisconnectFromAndShowDisconnectTips(IConnector* pOtherConnector) = 0;

        /// \brief 得到连接信息指针
        /// \return 连接信息指针
        virtual const IConnectorInfo* GetConnectorInfo()const = 0;


        /// \brief 设置连接信息，内部调用接口
        /// \param opConnectorInfo
        /// \return 返回true表示成功，否则表示失败
        virtual bool SetConnectorInfo(gcmp::OwnerPtr<IConnectorInfo> opConnectorInfo) = 0;

        /// Move connector's Origin to given position. Methods works both family instances and curves.
        ///\note Changing the location of the connector may lead to changes of location and geometry for
        /// the connector's host element and the hosts for other elements the element is connected to.
        /// This function has not tested properly because it is not yet used anywhere.
        /// \author zhangzg
        virtual bool MoveTo(const gcmp::Vector3d& targetPosition) = 0;

        /// \brief 判断连接点是否在链接文档中
        ///
        /// \return 返回true表示连接点在链接文档中，否则不是
        virtual bool IsInLinkDocument() const = 0;

        /// \brief 判断是否与MepElementJoin有连接关系
        ///
        /// \return 返回true表示有连接关系，否则没有连接关系
        virtual bool IsConnectedByMepElementJoin() const = 0;

        /// \brief 得到通过MepElementJoin被连接的对象指针
        ///
        /// \return 被连接对象的非const指针(通过MepElementJoin方式连接）
        virtual std::vector<gcmp::IElement*> GetConnectedElementViaElementJoins() = 0;

        /// \brief 得到通过MepElementJoin被连接的对象指针
        ///
        /// \return 被连接对象的const指针(通过MepElementJoin方式连接）
        virtual std::vector<const gcmp::IElement*> GetConnectedElementViaElementJoins() const = 0;

        /// \brief 得到通过MepElementJoin被连接的IConnector指针
        ///
        /// \return IConnector的非const指针(通过MepElementJoin方式连接）
        virtual std::vector<IConnector*> GetConnectedConnectorViaElementJoins() = 0;

        /// \brief 得到通过MepElementJoin被连接的IConnector指针
        ///
        /// \return IConnector的const指针(通过MepElementJoin方式连接）
        virtual std::vector<const IConnector*> GetConnectedConnectorViaElementJoins() const = 0;
            
        /// \brief 判断连接点是否可以伸出或退缩
        ///
        /// \return bool 如果可以伸缩，返回true;否则返回false
        virtual bool IsStretch() const = 0;

        /// \brief 是否允许同时与多个连接点产生连接关系
        /// 
        /// \return bool 如果允许同时与多个连接点产生连接关系，返回true;否则返回fals
        virtual bool IsAllowToMultiConnect() const = 0;
    };
}
